<template>
  <div class="user-list-container">
    <!-- 搜索区域 -->
    <el-card class="search-card">
      <el-form :inline="true" :model="searchForm" class="search-form">
        <el-form-item label="用户名">
          <el-input v-model="searchForm.userName" placeholder="请输入用户名" clearable />
        </el-form-item>
        <el-form-item label="昵称">
          <el-input v-model="searchForm.nickName" placeholder="请输入昵称" clearable />
        </el-form-item>
        <el-form-item label="状态">
          <el-select v-model="searchForm.status" placeholder="请选择状态" clearable>
            <el-option label="启用" value="1" />
            <el-option label="禁用" value="0" />
          </el-select>
        </el-form-item>
        <el-form-item>
          <el-button type="primary" @click="handleSearch">
            <el-icon><Search /></el-icon>搜索
          </el-button>
          <el-button @click="resetSearch">
            <el-icon><Refresh /></el-icon>重置
          </el-button>
        </el-form-item>
      </el-form>
    </el-card>

    <!-- 操作按钮区域 -->
    <div class="action-bar">
      <el-button type="primary" @click="handleAdd">
        <el-icon><Plus /></el-icon>新增用户
      </el-button>
    </div>

    <!-- 表格区域 -->
    <el-card class="table-card">
      <el-table v-loading="loading" :data="tableData" border style="width: 100%" table-layout="fixed">
        <el-table-column prop="id" label="序号" width="60" align="center" />
        <el-table-column prop="username" label="用户名" min-width="120" />
        <el-table-column prop="nickname" label="昵称" min-width="120" />
        <el-table-column prop="avatar" label="头像" width="100" align="center">
          <template #default="{ row }">
            <div class="avatar-container">
              <el-image
                v-if="row.avatar"
                class="avatar-image"
                :src="row.avatar"
                fit="cover"
                lazy
                :preview-src-list="[row.avatar]"
                :preview-teleported="true"
                :hide-on-click-modal="false"
              />
              <div v-else class="avatar-placeholder">无头像</div>
            </div>
          </template>
        </el-table-column>
        <el-table-column prop="email" label="邮箱" min-width="120" />
        <el-table-column prop="gender" label="性别" min-width="80">
          <template #default="{ row }">
            <el-tag v-if="row.gender === 0" type="danger">保密</el-tag>
            <el-tag v-if="row.gender === 1" type="success">男</el-tag>
            <el-tag v-if="row.gender === 2" type="info">女</el-tag>
          </template>
        </el-table-column>
        <el-table-column prop="status" label="状态" width="80" align="center">
          <template #default="{ row }">
            <el-tag :type="row.status ? 'success' : 'danger'">
              {{ row.status ? "启用" : "禁用" }}
            </el-tag>
          </template>
        </el-table-column>
        <el-table-column prop="createTime" label="创建时间" min-width="160" />
        <el-table-column label="操作" width="200" fixed="right" align="center">
          <template #default="{ row }">
            <el-button-group>
              <el-button type="primary" link @click="handleEdit(row)">
                <el-icon><Edit /></el-icon>编辑
              </el-button>
              <el-button type="primary" link @click="handleResetPassword(row)">
                <el-icon><Key /></el-icon>重置密码
              </el-button>
              <el-button type="danger" link @click="handleDelete(row)">
                <el-icon><Delete /></el-icon>删除
              </el-button>
            </el-button-group>
          </template>
        </el-table-column>
      </el-table>

      <!-- 分页 -->
      <div class="pagination-container">
        <el-pagination
          v-model:current-page="currentPage"
          v-model:page-size="pageSize"
          :page-sizes="[10, 20, 50, 100]"
          :total="total"
          layout="total, sizes, prev, pager, next, jumper"
          @size-change="handleSizeChange"
          @current-change="handleCurrentChange"
        />
      </div>
    </el-card>

    <!-- 用户表单对话框 -->
    <el-dialog :title="dialogTitle" v-model="dialogVisible" width="500px" @close="resetForm">
      <el-form ref="userFormRef" :model="userForm" :rules="userRules" label-width="80px">
        <el-form-item label="头像">
          <el-upload
            class="avatar-uploader"
            :action="uploadUrl"
            :headers="uploadHeaders"
            :show-file-list="false"
            :before-upload="beforeAvatarUpload"
            :on-success="handleAvatarSuccess"
            :on-error="handleAvatarError"
          >
            <img v-if="userForm.avatar" :src="userForm.avatar" class="avatar-preview" />
            <el-icon v-else class="avatar-uploader-icon"><Plus /></el-icon>
          </el-upload>
        </el-form-item>
        <el-form-item label="用户名" prop="username">
          <el-input v-model="userForm.username" placeholder="请输入用户名" :disabled="dialogType === 'edit'" />
        </el-form-item>
        <el-form-item label="昵称" prop="nickname">
          <el-input v-model="userForm.nickname" placeholder="请输入昵称" />
        </el-form-item>
        <el-form-item label="邮箱" prop="email">
          <el-input v-model="userForm.email" placeholder="请输入邮箱" />
        </el-form-item>
        <el-form-item label="性别" prop="gender">
          <el-radio-group v-model="userForm.gender">
            <el-radio :label="0">保密</el-radio>
            <el-radio :label="1">男</el-radio>
            <el-radio :label="2">女</el-radio>
          </el-radio-group>
        </el-form-item>
        <el-form-item label="手机号" prop="phone" v-if="dialogType === 'add'">
          <el-input v-model="userForm.phone" placeholder="请输入手机号" />
        </el-form-item>
        <el-form-item label="密码" prop="password" v-if="dialogType === 'add'">
          <el-input v-model="userForm.password" type="password" placeholder="请输入密码" show-password />
        </el-form-item>
        <el-form-item label="确认密码" prop="confirmPassword" v-if="dialogType === 'add'">
          <el-input v-model="userForm.confirmPassword" type="password" placeholder="请再次输入密码" show-password />
        </el-form-item>
        <el-form-item label="角色" prop="roleIds">
          <el-select v-model="userForm.roleIds" multiple placeholder="请选择角色">
            <el-option v-for="role in roleList" :key="role.id" :label="role.name" :value="role.id" />
          </el-select>
        </el-form-item>
        <el-form-item label="状态" prop="status">
          <el-radio-group v-model="userForm.status">
            <el-radio label="1" value="1">启用</el-radio>
            <el-radio label="0" value="0">禁用</el-radio>
          </el-radio-group>
        </el-form-item>
      </el-form>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="dialogVisible = false">取消</el-button>
          <el-button type="primary" @click="handleSubmit" :loading="submitLoading"> 确定 </el-button>
        </span>
      </template>
    </el-dialog>
  </div>
</template>

<script setup>
import { ref, reactive, onMounted, computed } from "vue";
import { ElMessage, ElMessageBox } from "element-plus";
import { Search, Plus, Edit, Delete, Refresh, Key } from "@element-plus/icons-vue";
import { getUserList, addUser, updateUser, deleteUser, resetUserPassword, getRoleList } from "@/api/user";
import { validatePasswordComplexity } from "@/utils/validators";
import { selectUserPermissions } from "@/api/role";
import { uploadFile, deleteFile } from "@/api/common";
import { getToken, setToken } from "@/utils/auth";
import { refresh } from "@/api/auth";

// 上传相关配置
const uploadUrl = process.env.VUE_APP_API_URL + "/upload";
const token = ref(getToken());
const uploadHeaders = computed(() => {
  return {
    Authorization: getToken(),
  };
});

// 搜索表单
const searchForm = reactive({
  userName: "",
  nickName: "",
  status: "",
});

// 表格数据
const loading = ref(false);
const tableData = ref([]);
const currentPage = ref(1);
const pageSize = ref(10);
const total = ref(0);

// 角色列表
const roleList = ref([]);

// 对话框控制
const dialogVisible = ref(false);
const dialogType = ref("add"); // add 或 edit
const dialogTitle = ref("新增用户");
const submitLoading = ref(false);

// 表单相关
const userFormRef = ref(null);
const userForm = reactive({
  id: "",
  username: "",
  nickname: "",
  email: "",
  phone: "",
  gender: 1,
  avatar: "",
  password: "",
  confirmPassword: "",
  roleIds: [],
  status: "1",
});

// 表单验证规则
const validateConfirmPassword = (rule, value, callback) => {
  if (value === "") {
    callback(new Error("请再次输入密码"));
  } else if (value !== userForm.password) {
    callback(new Error("两次输入密码不一致"));
  } else {
    callback();
  }
};

const userRules = {
  username: [
    { required: true, message: "请输入用户名", trigger: "blur" },
    { min: 3, max: 20, message: "长度在 3 到 20 个字符", trigger: "blur" },
  ],
  nickname: [
    { required: true, message: "请输入昵称", trigger: "blur" },
    { min: 2, max: 20, message: "长度在 2 到 20 个字符", trigger: "blur" },
  ],
  email: [
    { required: true, message: "请输入邮箱", trigger: "blur" },
    { type: "email", message: "请输入正确的邮箱地址", trigger: ["blur", "change"] },
  ],
  phone: [
    { required: true, message: "请输入手机号", trigger: "blur" },
    { pattern: /^1[3456789]\d{9}$/, message: "请输入正确的手机号", trigger: "blur" },
  ],
  password: [
    { required: true, message: "请输入密码", trigger: "blur" },
    { validator: validatePasswordComplexity, trigger: "blur" },
  ],
  confirmPassword: [
    { required: true, message: "请再次输入密码", trigger: "blur" },
    { validator: validateConfirmPassword, trigger: "blur" },
  ],
  roleIds: [{ required: true, message: "请选择角色", trigger: "change" }],
  status: [{ required: true, message: "请选择状态", trigger: "change" }],
};

// 获取用户列表
const fetchUserList = async () => {
  loading.value = true;
  try {
    const params = {
      ...searchForm,
      pageNum: currentPage.value,
      pageSize: pageSize.value,
    };
    const res = await getUserList(params);
    if (res.success) {
      tableData.value = res.data.list;
      total.value = res.data.total;
    }
  } catch (error) {
    console.error("获取用户列表失败：", error);
  } finally {
    loading.value = false;
  }
};

// 获取角色列表
const fetchRoleList = async () => {
  try {
    const res = await getRoleList();
    if (res.success) {
      roleList.value = res.data.list;
    }
  } catch (error) {
    console.error("获取角色列表失败：", error);
  }
};

// 头像上传前的验证
const beforeAvatarUpload = (file) => {
  const isImage = file.type.startsWith("image/");
  const isLt2M = file.size / 1024 / 1024 < 2;

  if (!isImage) {
    ElMessage.error("头像必须是图片格式!");
    return false;
  }
  if (!isLt2M) {
    ElMessage.error("头像大小不能超过 2MB!");
    return false;
  }
  return true;
};

// 头像上传成功
const handleAvatarSuccess = (res) => {
  if (res.success) {
    userForm.avatar = res.data;
  } else {
    ElMessage.error("头像上传失败");
  }
};

// 头像上传失败
const handleAvatarError = async (error, file) => {
  try {
    const refreshResult = await refresh();
    if (refreshResult.success) {
      //更新token
      setToken(refreshResult.data);
      // 更新响应式 token
      token.value = refreshResult.data;
      // 重新上传
      const data = new FormData();
      data.append("file", file.raw || file);
      const uploadResult = await uploadFile(data);
      if (uploadResult.success) {
        userForm.avatar = uploadResult.data;
      } else {
        ElMessage.error("图片上传失败");
      }
    } else {
      ElMessage.error("图片上传失败");
    }
  } catch (err) {
    console.error("图片上传失败:", error);
    ElMessage.error("图片上传失败");
  }
};

// 搜索
const handleSearch = () => {
  currentPage.value = 1;
  fetchUserList();
};

// 重置搜索
const resetSearch = () => {
  Object.keys(searchForm).forEach((key) => {
    searchForm[key] = "";
  });
  handleSearch();
};

// 分页
const handleSizeChange = (val) => {
  pageSize.value = val;
  fetchUserList();
};

const handleCurrentChange = (val) => {
  currentPage.value = val;
  fetchUserList();
};

// 新增用户
const handleAdd = () => {
  dialogType.value = "add";
  dialogTitle.value = "新增用户";
  dialogVisible.value = true;
};

// 编辑用户
const handleEdit = (row) => {
  dialogType.value = "edit";
  dialogTitle.value = "编辑用户";
  Object.assign(userForm, {
    id: row.id,
    username: row.username,
    nickname: row.nickname,
    email: row.email || "",
    gender: row.gender || 0,
    avatar: row.avatar || "",
    roleIds: row.userRoleList?.map((item) => item.roleId) || [],
    status: row.status ? "1" : "0",
  });
  dialogVisible.value = true;
};

// 重置密码
const handleResetPassword = (row) => {
  ElMessageBox.confirm("确定要重置该用户的密码吗？", "提示", {
    confirmButtonText: "确定",
    cancelButtonText: "取消",
    type: "warning",
  })
    .then(async () => {
      try {
        const res = await resetUserPassword(row.id);
        if (res.success) {
          ElMessage.success("密码重置成功(默认密码为Dcsgo.com.cn-666)");
        }
      } catch (error) {
        console.error("密码重置失败：", error);
      }
    })
    .catch(() => {
      // 用户点击了取消，不需要任何处理
    });
};

// 删除用户
const handleDelete = (row) => {
  ElMessageBox.confirm("确定要删除该用户吗？", "提示", {
    confirmButtonText: "确定",
    cancelButtonText: "取消",
    type: "warning",
  })
    .then(async () => {
      try {
        const res = await deleteUser(row.id);
        if (res.success) {
          ElMessage.success("删除成功");
          fetchUserList();
        }
      } catch (error) {
        console.error("删除失败：", error);
      }
    })
    .catch(() => {
      // 用户点击了取消，不需要任何处理
    });
};

// 提交表单
const handleSubmit = async () => {
  if (!userFormRef.value) return;

  await userFormRef.value.validate(async (valid) => {
    if (valid) {
      submitLoading.value = true;
      try {
        const submitData = { ...userForm };
        // 删除确认密码字段
        delete submitData.confirmPassword;

        const res = dialogType.value === "add" ? await addUser(submitData) : await updateUser(submitData);

        if (res.success) {
          // 刷新权限
          const permRes = await selectUserPermissions();
          if (permRes.success) {
            localStorage.setItem("permissions", JSON.stringify(permRes.data));
          }
          ElMessage.success(`${dialogType.value === "add" ? "添加" : "更新"}成功`);
          dialogVisible.value = false;
          fetchUserList();
        }
      } catch (error) {
        console.error(`${dialogType.value === "add" ? "添加" : "更新"}失败：`, error);
      } finally {
        submitLoading.value = false;
      }
    }
  });
};

// 重置表单
const resetForm = () => {
  if (userFormRef.value) {
    userFormRef.value.resetFields();
  }
  Object.keys(userForm).forEach((key) => {
    if (key === "status") {
      userForm[key] = "1";
    } else if (key === "gender") {
      userForm[key] = 1;
    } else if (key === "roleIds") {
      userForm[key] = [];
    } else {
      userForm[key] = "";
    }
  });
};

// 初始化
onMounted(() => {
  fetchUserList();
  fetchRoleList();

  // 获取用户权限
  selectUserPermissions().then((res) => {
    if (res.success) {
      localStorage.setItem("permissions", JSON.stringify(res.data));
    }
  });
});
</script>

<style scoped>
.user-list-container {
  padding: 20px;
}

.search-card {
  margin-bottom: 20px;
}

.search-form {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}

.action-bar {
  margin-bottom: 20px;
}

.table-card {
  margin-bottom: 20px;
}

.pagination-container {
  margin-top: 20px;
  display: flex;
  justify-content: flex-end;
}

:deep(.el-dialog__body) {
  padding-top: 10px;
}

.dialog-footer {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
}

.avatar-container {
  width: 50px;
  height: 50px;
  margin: 0 auto;
  position: relative;
  overflow: hidden;
  border-radius: 4px;
}

.avatar-image {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.avatar-placeholder {
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  background-color: #f5f7fa;
  color: #909399;
  font-size: 12px;
}

.avatar-uploader {
  display: flex;
  justify-content: center;
}

.avatar-uploader :deep(.el-upload) {
  border: 1px dashed #d9d9d9;
  border-radius: 6px;
  cursor: pointer;
  position: relative;
  overflow: hidden;
  transition: var(--el-transition-duration-fast);
}

.avatar-uploader :deep(.el-upload:hover) {
  border-color: var(--el-color-primary);
}

.avatar-uploader-icon {
  font-size: 28px;
  color: #8c939d;
  width: 100px;
  height: 100px;
  text-align: center;
  display: flex;
  justify-content: center;
  align-items: center;
}

.avatar-preview {
  width: 100px;
  height: 100px;
  display: block;
  object-fit: cover;
}
</style>
